package com.hxzy.controller.front.alipay;

import cn.hutool.core.util.StrUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hxzy.common.enums.AckCode;
import com.hxzy.common.exception.ServiceException;
import com.hxzy.config.AlipayConfig;
import com.hxzy.entity.Orders;
import com.hxzy.service.OrdersService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @Author wy
 * @Description TODO
 * @Date 2023/7/25 11:42
 * @Version 1.0
 */
@Log4j2
@Api(tags = "支付宝支付")
@RestController
@RequestMapping(value = "/front/alipay")
public class AlipayController {

    @Autowired
    private OrdersService ordersService;


    @ApiOperation(value = "1、向支付宝提交支付申请")
    @GetMapping(value = "/{orderNumber}")
    public void submitAlipay(@PathVariable(value = "orderNumber") String orderNumber, HttpServletResponse response) throws UnsupportedEncodingException {
        log.info(orderNumber);
       //1、查询订单
        if(StrUtil.isBlank(orderNumber)){
            throw new ServiceException(AckCode.SYSTEM_PARAM_FAIL);
        }

        Orders dbOrder = this.ordersService.getOne(new LambdaQueryWrapper<Orders>().eq(Orders::getNumber, orderNumber));
        if(Objects.isNull(dbOrder)){
            throw new ServiceException(AckCode.NOT_FOUND_DATA);
        }
        //已经支付过了订单
        if(!dbOrder.getStatus().equals("1")){
            throw new ServiceException(AckCode.ORDER_STATUA_ERROR);
        }

        //2、向支付宝发起支付申请 ( 必须是一个网页，不能是json字符串)
        // 商户订单号，商户网站订单系统中唯一订单号，必填
        String out_trade_no = orderNumber+"";
        // 订单名称，必填
        String merchandiserName=this.ordersService.searchByMerchandiserName(orderNumber);
        String subject = "向"+merchandiserName+"付款";

        // 付款金额(保留2位小数)，必填
        String total_amount= dbOrder.getAmount().setScale(2, RoundingMode.HALF_UP).doubleValue()+"";
        // 商品描述，可空
        String body =merchandiserName;
        // 超时时间 可空
        String timeout_express="2m";

        /**********************/
        // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
        //调用RSA签名方式
        AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY,AlipayConfig.SIGNTYPE);
        AlipayTradeWapPayRequest alipay_request=new AlipayTradeWapPayRequest();

        // 封装请求支付信息
        AlipayTradeWapPayModel model=new AlipayTradeWapPayModel();
        model.setOutTradeNo(out_trade_no);
        model.setSubject(subject);
        model.setTotalAmount(total_amount);
        model.setBody(body);
        model.setTimeoutExpress(timeout_express);

        alipay_request.setBizModel(model);
        // 设置异步通知地址
        alipay_request.setNotifyUrl(AlipayConfig.notify_url);
        // 设置同步地址
        alipay_request.setReturnUrl(AlipayConfig.return_url);

        // form表单生产
        String form = "";
        try {
            // 调用SDK生成表单
            form = client.pageExecute(alipay_request).getBody();
            log.info(form);
            response.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
            //直接将完整的表单html输出到页面
            response.getWriter().write(form);
            response.getWriter().flush();
            response.getWriter().close();
        } catch (AlipayApiException | IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @ApiOperation(value = "2、支付宝通知支付情况",hidden = true)
    @PostMapping(value = "/notify")
    public void alipay_notify(HttpServletRequest request,HttpServletResponse response) throws AlipayApiException, ParseException, IOException {

        PrintWriter out= response.getWriter();

        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            params.put(name, request.getParameter(name));
        }

        log.info(params.toString());
         //商户订单号
        String out_trade_no = params.get("out_trade_no");
        //支付宝交易号
        String trade_no =params.get("trade_no");
        //实际支付金额
        String total_amount= params.get("total_amount");
        //交易时间 yyyy-MM-dd HH:mm:ss
        String gmt_payment=params.get("gmt_payment");
        //交易状态
        String trade_status =  params.get("trade_status");

        SimpleDateFormat smf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        //计算得出通知验证结果
        boolean verify_result = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, "RSA2");
        if(verify_result){
            //支付成功
            if (trade_status.equals("TRADE_SUCCESS")){
                //更新订单状态
                Orders dbOrder = this.ordersService.getOne(new LambdaQueryWrapper<Orders>().eq(Orders::getNumber, out_trade_no));
                dbOrder.setStatus("2");
                dbOrder.setCheckoutTime(smf.parse(gmt_payment));
                dbOrder.setPayPrice(new BigDecimal(total_amount));
                dbOrder.setPayReceipt(trade_no);
                this.ordersService.updateById(dbOrder);


                out.println("success");
            }
        }else{
            out.println("fail");
        }
    }





}
